package com.example.lock.zk.impl;

import com.example.lock.zk.ZKLock;
import com.example.util.LockContext;
import com.example.util.ZkUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @Description: 锁模版方法
 * @Author: mingtian
 * @CreateDate: 2020/12/5 11:50
 * @Version: 1.0
 */
@Component
public abstract class AbstractLockTemplate implements ZKLock {

    /**
     * 打印日志
     */
    private Logger logger = LoggerFactory.getLogger(AbstractLockTemplate.class);

    @Value("${server.port}")
    private String serverPort;


    @Override
    public boolean getLock() {
//        for (int i = 0; i < 5; i++) {
        boolean result = tryLock();
        if (result) {
            logger.info("serverPort:{}获取锁成功", serverPort);
            return true;
        }
//        }
        logger.info("serverPort:{}获取锁失败", serverPort);
        // 获取锁失败  当前线程阻塞
        waitLock();
        // 唤醒线程之后重新获取锁
        boolean lock = getLock();
        return lock;
    }

    /**
     * 阻塞
     */
    protected abstract void waitLock();

    /**
     * 获取锁
     *
     * @return
     */
    protected abstract boolean tryLock();


    /**
     * 释放锁(关闭连接、删除临时节点)
     */
    @Override
    public void releaseLock() {
        logger.info("释放锁,serverPort:{}", serverPort);
        // 关闭连接
        ZkUtils.close();
        // 移除当前线程信息
        LockContext.remove();
    }
}